#include <string>
#include <list>
#include <sstream>
#include <map>
#include "login.h"
#include "main.h"
#include "global.h"
#include "Tools/myLog.h"
#include "Tools/rfile.h"
#include "Tools/message.h"
#include "Tools/myLog.h"
#include "Tools/utility.h"
#include "Character/User.h"
#include "Room/room.h"

login::login(){};
login::~login(){};

void login::loginProcess(User *u)
{
	myLog m = myLog("login");
	bool isLoginScussess;
	isLoginScussess = false;
	extern map<string, User*> AllUser;
	map<string, User*>::iterator itAllUser;
	switch (u->UserProfile.iLoginStatus)
	{
		case 1:
			//User input : none
			//ask username and password or creat a new account
			u->OutputMessage(message::GetNormalMessage(0));
			u->OutputMessage(message::GetNormalMessage(1));
			u->UserProfile.iLoginStatus = 2;
			//change statuc to 2 ( ask user input user name)
			break;
		case 2:
			//User input : Keyword "NEW" or username.
			//get username
			if (utility::string2upper(u->UserProfile.strUserInput) == "NEW")
			{
				//User request create a new account.
				//change status to 3
				u->UserProfile.strUserInput = "";
				u->OutputMessage(message::GetNormalMessage(4));
				u->UserProfile.iLoginStatus = 3;
			}
			else
			{
				//Get user name.
				u->UserData[ Const.userName ] = u->UserProfile.strUserInput;
				if (u->IsUserExist())
				{
					//Change status to 4, try to get user password.
					u->OutputMessage(message::GetNormalMessage(2));
					u->UserProfile.iLoginStatus = 4;
				}
				else
				{
					//Change status to 4, ask user would like using this name create a new account.
					u->OutputMessage(message::GetNormalMessage(8));
					u->UserProfile.iLoginStatus = 5;
				}
			}
			break;
		case 3:
			//User input : new user name.
			u->UserData[ Const.userName  ] = u->UserProfile.strUserInput;
			u->OutputMessage(message::GetNormalMessage(5));
			u->UserProfile.iLoginStatus = 31;
			break;
		case 31:
			//User input : password
			u->UserProfile.passWord = u->UserProfile.strUserInput;
			u->OutputMessage(message::GetNormalMessage(12));
			u->UserProfile.iLoginStatus = 311;
			break;
		case 311:
			//User input : confirm password
			if (u->UserProfile.passWord == u->UserProfile.strUserInput)
			{
				u->UserData[ Const.passWord ] = u->UserProfile.strUserInput;
				if (u->Save())
				{
					u->OutputMessage(message::GetNormalMessage(14));
					isLoginScussess = true;
				}
				else
				{
					u->OutputMessage(message::GetNormalMessage(15));
					u->UserProfile.iLoginStatus = 1;
				}
			}
			else
			{
				//Password confirm faild.
				u->UserProfile.passWord = "";
				u->OutputMessage(message::GetNormalMessage(13));
				u->OutputMessage(message::GetNormalMessage(5));
				u->UserProfile.iLoginStatus = 31;
			}
			break;
		case 4:
			//Get user password.
			u->UserProfile.passWord = u->UserProfile.strUserInput;
			if (u->Auth())
			{
				isLoginScussess = true;
			}
			else
			{
				u->OutputMessage(message::GetNormalMessage(9));
				u->UserProfile.ierrorTimes++;
				if (u->UserProfile.ierrorTimes > 2)
				{
					u->OutputMessage(message::GetNormalMessage(1001));
					u->UserProfile.blNeedKickOut = true;
				}
				else
				{
					u->OutputMessage(message::GetNormalMessage(0));
					u->OutputMessage(message::GetNormalMessage(1));
					u->UserProfile.iLoginStatus = 2;
				}
			}
			break;
		case 5:
			//User input : Y or N, Y for using this new name create a new account.
			if (utility::string2upper(u->UserProfile.strUserInput) == "Y")
			{
				u->OutputMessage(message::GetNormalMessage(5));
				u->UserProfile.iLoginStatus = 31;
			}
			else if (utility::string2upper(u->UserProfile.strUserInput) == "N")
			{
				u->OutputMessage(message::GetNormalMessage(7));
				u->OutputMessage(message::GetNormalMessage(1));
				u->UserProfile.iLoginStatus = 2;
			}
			else
			{
				u->OutputMessage(message::GetNormalMessage(99));
				u->OutputMessage(message::GetNormalMessage(8));
			}
			break;
		case 6:
			//There are another the same account already logined.
			//Asking user will kickout or not.
			//User input : Y or N, Y for kickout the old connection.
			
			if (utility::string2upper(u->UserProfile.strUserInput) == "Y")
			{
				itAllUser = AllUser.find(u->UserData[ Const.userName ]);
	
				if (itAllUser == AllUser.end())
				{
					//Old logined account has been logout.
					isLoginScussess = true;
					m.writelog("Old one already not here now. Don't need kickout old account.");
				}
				else
				{
					//need kickout old one.
					//send a message to old one.
					(*itAllUser->second).OutputMessage(message::GetNormalMessage(17));
					User *LastUser;
					LastUser = itAllUser->second;
					LastUser->KickOut();
					u->OutputMessage(message::GetNormalMessage(3));
					u->UserProfile.isLogined = true;
					m.writelog("second login and kickout old one.");
				}
			}
			else if (utility::string2upper(u->UserProfile.strUserInput) == "N")
			{
				u->OutputMessage(message::GetNormalMessage(7));
				u->OutputMessage(message::GetNormalMessage(1));
				u->UserProfile.iLoginStatus = 2;
			}
			else
			{
				u->OutputMessage(message::GetNormalMessage(99));
				u->OutputMessage(message::GetNormalMessage(16));
			}
			break;
		default:
			break;
	}
	
	if (isLoginScussess)
	{
		//Check this user is on line or not.
		itAllUser = AllUser.find(u->UserData[ Const.userName ]);
		m.writelog(u->UserData[ Const.userName ]);
		if (itAllUser == AllUser.end())
		{
			//Put user information into global object AllUser
			AllUser[u->UserData[ Const.userName ]] = u;
			u->UserProfile.isLogined = true;
			u->OutputMessage(message::GetNormalMessage(3));
			m.writelog("first login");
		}
		else
		{
			u->OutputMessage(message::GetNormalMessage(16));
			u->UserProfile.iLoginStatus = 6;
			m.writelog("another login");
		}
	}
}

bool login::blUserIsExist(std::string strUserName)
{
	string user_filename = "./UserFolder/" + strUserName + "_profile.txt";
	return rfile::isExist(user_filename);
}
